package init.auto

import org.gradle.api.tasks.Internal;
import java.util.regex.Pattern
import org.gradle.api.DefaultTask;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.*;
import org.gradle.api.tasks.bundling.*;
import javax.inject.Inject;
import org.gradle.api.*;
import org.gradle.api.file.*;
import groovy.xml.*;
import org.gradle.util.internal.GFileUtils;


// https://docs.gradle.org/current/javadoc/org/gradle/api/DefaultTask.html
abstract class AutoScanPatchTask extends DefaultTask {

     // !!!!!! 构造函数中不能直接使用输入，必须在doLast中使用（@Input 属性在配置阶段被赋值，构造函数执行时，配置阶段尚未开始！）
    @Input
    abstract Property<org.gradle.api.Project> getProject1()
    @Input
    abstract Property<String> getGitPatchModuleName()
    @Input
    abstract Property<String> getGitPatchDescription()
    @Input
    abstract Property<String> getGitPatchLogCommand()
    @Input
    abstract Property<String> getGitPatchDiffCommand()
    @Input
    abstract Property<String> getGitPatchDepartment()
    @Input
    abstract Property<String> getGitPatchAuthor()
    @Input
    abstract Property<String> getConsoleEncoding()
    @Input
    abstract Property<String> getEclipseClassMainOutput()

    @Internal
    def gitPatchModulePath
    @Internal
    def gitPatchOutputPath
    @Internal
    def realModuleName
    @Internal
    def prefixColor
    @Internal
    def prefixMainColor
    @Internal
    def prefixErrorColor

    @Internal
    def gitPatchFiles
    @Internal
    def allFileLog
    @Internal
    def modulesMetaInfoClassesSources
    @Internal
    def modulesMetaInfoClasses
    @Internal
    def modulesLibClassesSources
    @Internal
    def modulesLibClasses
    @Internal
    def modulesNccloudClassesSources
    @Internal
    def modulesNccloudClasses
    @Internal
    def modulesMetaData
    @Internal
    def modulesMetaInfo
    @Internal
    def resources
    @Internal
    def yyconfig
    @Internal
    def patchOutput
    @Internal
    def suffix
    @Internal
    def summary
    @Internal
    def branchName


    @TaskAction
    def init() {

        // 模块物理路径  -- git执行根路径
        gitPatchModulePath = project1.get().project(":${gitPatchModuleName.get()}").projectDir.absolutePath.replace(File.separator, '/')
        // 模块编译输出物理路径
        gitPatchOutputPath = "${gitPatchModulePath}/${eclipseClassMainOutput.get()}"

        // 扫描模块别名
        realModuleName = ensureModuleName(gitPatchModulePath)
        // 扫描输出目录
        patchOutput = "${project1.get().rootDir.path.replace(File.separator, '/')}/patch/${realModuleName}/"

        suffix = new Date().format("yyyy-MM-dd HH:mm:ss")
        // 补丁提交摘要
        summary = ''
        branchName = ''

        prefixColor = "\033[38;2;41;184;219m * \033[0m"
        prefixMainColor = "\033[38;2;41;184;219m >>>>> \033[0m"
        prefixErrorColor = "\033[38;255;0;0;219m <<<<< \033[0m"
        gitPatchFiles = []
        modulesMetaInfoClassesSources = []
        modulesMetaInfoClasses = []
        modulesLibClassesSources = []
        modulesLibClasses = []
        modulesNccloudClassesSources = []
        modulesNccloudClasses = []
        modulesMetaData = []
        modulesMetaInfo = []
        resources = []
        yyconfig = []
        allFileLog = []
    }

    AutoScanPatchTask() {
        setGroup("ocean patch")
        setDescription("扫描模块并生成补丁任务")

        logger.lifecycle("1. 扫描 git index/stage 暂存区（未提交的文件）...")
        // 1. 扫描 git index/stage 暂存区（未提交的文件）
        doFirst {
            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'powershell', '/c', ' git status --porcelain --untracked-files=no | ForEach-Object { $_.Substring(3) } '
                } else {
                    //on linux:
                    commandLine 'bash', '-c', ' git status --porcelain --untracked-files=no | cut -c4- '
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }
            def out = res.getStandardOutput().getAsText().get().split('\n')

            out.each {
                if (it.contains('/')) {
                    gitPatchFiles.add(it.strip())
                }
            }
        }



        // 2. 扫描 git remote/repository 仓库（拉取指定记录） -E 指定基于POSIX扩展正则表达式
        doLast {
            if (gitPatchLogCommand.get().contains('git log')) {
                logger.lifecycle("2. 扫描远程仓库（拉取提交记录）...")
            }

            
            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'cmd', '/c', gitPatchLogCommand.get()
                } else {
                    //on linux:
                    commandLine 'bash', '-c', gitPatchLogCommand.get()
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }

            def fs = res.getStandardOutput().getAsText().get().split("\n")
            fs = fs as List

            gitPatchFiles = gitPatchFiles.plus(fs)
        }



        // 3. 指定远程分支名称：origin/release-bipp2505
        doLast {
            if (gitPatchDiffCommand.get().contains('git log')) {
                logger.lifecycle("3. 扫描对比分支（拉取差异记录）...")
            }

            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'powershell', '/c', gitPatchDiffCommand.get()
                } else {
                    //on linux:
                    commandLine 'bash', '-c', gitPatchDiffCommand.get()
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }

            def fs = res.getStandardOutput().getAsText().get().split("\n")
            fs = fs as List

            gitPatchFiles = gitPatchFiles.plus(fs)
        }



        doLast {
            
            gitPatchFiles.each {String name ->
                if (name && name.contains('/')) {

                    def filename = name

                    name = "${gitPatchModulePath}/${name}"

                    // TODO 中文文件名为八进制无法解析
                    if (project1.get().file(name).exists()) {
                        allFileLog.add("${realModuleName}/${filename}")
                    }


                    if (name.contains('src/private/')) {

                        modulesMetaInfoClassesSources.add(name)
                        modulesMetaInfoClasses.add(name.split('src/private/')[1].replace('.java',''))

                    } else if (name.contains('src/public/')) {

                        modulesLibClassesSources.add(name)
                        modulesLibClasses.add(name.split('src/public/')[1].replace('.java',''))

                    } else if (name.contains('src/client/nccloud')) {
                        
                        modulesNccloudClassesSources.add(name)
                        modulesNccloudClasses.add(name.split('src/client/')[1].replace('.java',''))

                    } else if (name.contains('/METADATA')) {
                        modulesMetaData.add(name.split('/METADATA')[1])

                    } else if (name.contains('/META-INF')) {
                        modulesMetaInfo.add(name.split('/META-INF')[1])

                    } else if (name.contains('/resources/')) {
                        resources.add(name.split('/resources')[1])

                    } else if (name.contains('src/client/yyconfig/')) {
                        yyconfig.add(name.split('src/client')[1])
                    }
                    // println file(name)
                }
            }

            modulesMetaInfoClassesSources = modulesMetaInfoClassesSources.unique()
            modulesMetaInfoClasses = modulesMetaInfoClasses.unique()

            modulesLibClassesSources = modulesLibClassesSources.unique()
            modulesLibClasses = modulesLibClasses.unique()

            modulesNccloudClassesSources = modulesNccloudClassesSources.unique()
            modulesNccloudClasses = modulesNccloudClasses.unique()

            modulesMetaData = modulesMetaData.unique()
            modulesMetaInfo = modulesMetaInfo.unique()
            resources = resources.unique()
            yyconfig = yyconfig.unique()

        }


        doLast {
            // 删除patch路径
            project1.get().delete project1.get().file(patchOutput)
        }



        doLast{
            println "${prefixColor}${gitPatchModuleName.get()} copy private starting ..."
            def outputDir = "${patchOutput}/replacement/modules/${realModuleName}/META-INF/classes"

            project1.get().copy {
                from project1.get().fileTree("${gitPatchOutputPath}")
                include '/n*/**/*.0' // nccloud ncc nc
                include '/o*/**/*.0' // org
                include '/j*/**/*.0'
                include { details ->
                    modulesMetaInfoClasses.any{
                        def classpath = details.file.absolutePath.replace(File.separator, '/')
                        if (classpath.contains(it+".") || classpath.contains(it+"\$")) {
                            return true
                        }
                    }
                    // def exists = modulesMetaInfoClasses.count{ details.file.name.endsWith(it) }
                }
                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }

            def privatePattern = Pattern.compile("src${File.separator}private${File.separator}", Pattern.LITERAL)
            project1.get().copy {
                from modulesMetaInfoClassesSources
                into (outputDir)
                // Flatten the hierarchy by setting the path
                // of all files to their respective basename
                eachFile { detail ->
                    path = privatePattern.split(detail.file.path)[1]
                }
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast{
            println "${prefixColor}${gitPatchModuleName.get()} copy public starting ..."
            def outputDir = "${patchOutput}/replacement/modules/${gitPatchModuleName.get()}/classes"
            // nccmain模块物理路径
            def nccmainModuleDir = project1.get().project(":nccmain").projectDir.absolutePath.replace(File.separator, '/')
            // nccmain模块编译输出的对应模块的public编译输出物理路径
            def publicModuleOutput = "${nccmainModuleDir}/bin/${gitPatchModuleName.get()}"

            project1.get().copy {
                from project1.get().fileTree("${publicModuleOutput}")
                include '/n*/**/*.0' // nccloud ncc nc
                include '/o*/**/*.0' // org
                include '/j*/**/*.0'
                include { details ->
                    modulesLibClasses.any{
                        def classpath = details.file.absolutePath.replace(File.separator, '/')
                        if (classpath.contains(it+".") || classpath.contains(it+"\$")) {
                            return true
                        }
                    }
                }
                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }

            def publicPattern = Pattern.compile("src${File.separator}public${File.separator}", Pattern.LITERAL)
            project1.get().copy {
                from modulesLibClassesSources
                into (outputDir)
                // Flatten the hierarchy by setting the path
                // of all files to their respective basename
                eachFile { detail ->
                    path = publicPattern.split(detail.file.path)[1]
                }
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast{
            println "${prefixColor}${gitPatchModuleName.get()} copy nccloud starting ..."
            def outputDir = "${patchOutput}/replacement/hotwebs/nccloud/WEB-INF/classes"
            // nccweb模块物理路径
            def nccwebModuleDir = project1.get().project(":nccweb").projectDir.absolutePath.replace(File.separator, '/')
            // nccweb模块编译输出的对应模块的client编译输出物理路径
            def nccwebModuleOutput = "${nccwebModuleDir}/bin/${gitPatchModuleName.get()}"

            project1.get().copy {
                from project1.get().fileTree("${nccwebModuleOutput}")
                include '/nccloud*/**/*.0'
                include { details ->
                    modulesNccloudClasses.any{
                        def classpath = details.file.absolutePath.replace(File.separator, '/')
                        if (classpath.contains(it+".") || classpath.contains(it+"\$")) {
                            return true
                        }
                    }
                }
                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }

            def clientPattern = Pattern.compile("src${File.separator}client${File.separator}", Pattern.LITERAL)
            project1.get().copy {
                from modulesNccloudClassesSources
                include { details ->
                    details.file.path.replace(File.separator, '/').contains('nccloud')
                }
                into (outputDir)
                // Flatten the hierarchy by setting the path
                // of all files to their respective basename
                eachFile { detail ->
                    path = clientPattern.split(detail.file.path)[1]
                }
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast {
            println "${prefixColor}${gitPatchModuleName.get()} copy yyconfig starting ..."
            def outputDir = "${patchOutput}/replacement/hotwebs/nccloud/WEB-INF/extend"
            // nccweb模块物理路径
            def nccwebModuleDir = project1.get().project(":nccweb").projectDir.absolutePath.replace(File.separator, '/')
            // nccweb模块编译输出的对应模块的client编译输出物理路径
            def clientModuleOutput = "${nccwebModuleDir}/bin/${gitPatchModuleName.get()}"
            project1.get().copy {
                from project1.get().fileTree("${clientModuleOutput}")
                include '/yyconfig/**/*.0'
                include { details ->
                    yyconfig.any{ details.file.path.replace(File.separator, '/').endsWith(it) }
                }
                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast {
            println "${prefixColor}${gitPatchModuleName.get()} copy resources starting ..."
            // 资源不存在模块名
            def outputDir = "${patchOutput}/replacement/resources/"
            project1.get().copy {
                from project1.get().fileTree("${gitPatchOutputPath}")
                include '/**/*.0'
                include { details ->
                    resources.any{ details.file.path.replace(File.separator, '/').endsWith(it) }
                }
                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast {
            println "${prefixColor}${gitPatchModuleName.get()} copy metaData starting ..."
            def outputDir = "${patchOutput}/replacement/modules/${gitPatchModuleName.get()}/METADATA"
            project1.get().copy {
                from project1.get().fileTree("${gitPatchOutputPath}")
                include '/**/*.0'
                include { details ->
                    modulesMetaData.any{ details.file.path.replace(File.separator, '/').endsWith(it) }
                }

                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast {
            println "${prefixColor}${gitPatchModuleName.get()} copy meta-inf starting ..."
            def outputDir = "${patchOutput}/replacement/modules/${gitPatchModuleName.get()}/META-INF"
            project1.get().copy {
                from project1.get().fileTree("${gitPatchOutputPath}")
                include '/**/*.0'
                include { details ->
                    modulesMetaInfo.any{ details.file.path.replace(File.separator, '/').endsWith(it) }
                }

                into(outputDir)
                duplicatesStrategy = DuplicatesStrategy.INCLUDE
                includeEmptyDirs = false
            }
        }



        doLast {
            if (!project1.get().file(patchOutput).exists()) {
                def errorDetail = """
                    |    >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                    |
                    |    模块[${gitPatchModuleName.get()}]没有搜索到变动的文件！请将修改的文件提交到[GIT暂存区]或者修改[gradle.propeties]文件中的[*Command]参数
                    |
                    |    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                    |""".stripMargin()
                throw new IOException(errorDetail)
                // 如果需要仅跳过当前任务
                // throw new StopExecutionException(errorDetail)
            }
            
        }


        
        doLast {
            def outputxml = new File("${patchOutput}/installpatch.xml")

            outputxml.withWriter("UTF-8") { writer ->
                // Create MarkupBuilder with 4 space indent
                def xml = new MarkupBuilder(new IndentPrinter(writer, "    ", true))
                xml.doubleQuotes = true
                xml.mkp.xmlDeclaration(version: '1.0', encoding: "UTF-8")
                xml.installpatch() {
                    'soscopy'() {
                        'sosfrom'('/replacement/modules/')
                        'to'('/modules/')
                    }
                }
            }

            def text2 = outputxml.text.replace('sos','')
            outputxml.write(text2, "UTF-8")
        }

        // 1. 获取提交摘要 -- git log
        doLast {
            if (!gitPatchLogCommand.get().contains("--name-only")) {
                logger.warn(" - 参数：gitPatchLogCommand 不存在，或不包含 --name-only，跳过后续操作")
                return
            }

            logger.lifecycle(" > 处理变更提交摘要（git log）...")

            def gitOnelineRepositoryCommand = gitPatchLogCommand.get().replace('--pretty=format:', '').replace("--name-only", '--pretty=format:"%h %ad %an | %s" --date=format:"%Y-%m-%d"')

            // 提交历史文件
            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'cmd', '/c', gitOnelineRepositoryCommand
                } else {
                    //on linux:
                    commandLine 'bash', '-c', gitOnelineRepositoryCommand
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }

            summary = res.getStandardOutput().getAsText().get()
        }

        // 2. 获取提交摘要 -- git diff
        doLast {
            // git log --pretty=format:"%h %ad %an | %s" --date=format:"%Y-%m-%d"  origin/release-bipp2505..HEAD
            if (!gitPatchDiffCommand.get().contains("--name-only")) {
                logger.warn(" - 参数：gitPatchDiffCommand 参数不存在，或不包含 --name-only，跳过后续操作")
                return
            }

            logger.lifecycle(" > 处理变更提交摘要（git diff）...")

            def gitOnelineRepositoryCommand = ' git log --pretty=format:"%h %ad %an | %s" --date=format:"%Y-%m-%d" ' + gitPatchDiffCommand.get().split('--name-only')[1].trim() + '..HEAD'
            // 提交历史文件
            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'cmd', '/c', gitOnelineRepositoryCommand
                } else {
                    //on linux:
                    commandLine 'bash', '-c', gitOnelineRepositoryCommand
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }

            summary += "\n\n"
            summary += res.getStandardOutput().getAsText().get()
        }

        // 获取提交分支
        doLast {
            def gitRepositoryCommand = 'git rev-parse --abbrev-ref HEAD'
            // 提交历史文件
            def res = project1.get().getProviders().exec {
                workingDir gitPatchModulePath

                if (System.getProperty('os.name').toLowerCase(Locale.ROOT).contains('windows')) {
                    //on windows:
                    commandLine 'powershell', '/c', gitRepositoryCommand
                } else {
                    //on linux:
                    commandLine 'bash', '-c', gitRepositoryCommand
                }
            }

            // res.getResult().get().assertNormalExitValue()
            def err = res.getStandardError().getAsText().getOrNull()
            if (err != null && !err.isEmpty()) {
                throw new RuntimeException(err)
            }

            branchName = res.getStandardOutput().getAsText().get()
        }


        doLast { 

            def classesPattern = Pattern.compile("classes${File.separator}", Pattern.LITERAL)

            def classtext = ''
            def outputclasses = project1.get().fileTree( dir: "${patchOutput}", includes:['**/*.class*'])
            outputclasses.each {
                def classpath = classesPattern.split(it.path)[1].replace('.class','').replace(File.separator, '.')
                
                // println classpath
                classtext += classpath
                classtext += ','
            }
            classtext = classtext.replaceAll(',$','')

            def outputxml = new File("${patchOutput}/packmetadata.xml")
            def id1 = "855448f5-80e9-4b89-" + "${Math.random()}".minus('0.')

            outputxml.withWriter("UTF-8") { writer ->
                // Create MarkupBuilder with 4 space indent
                def xml = new MarkupBuilder(new IndentPrinter(writer, "    ", true))
                xml.doubleQuotes = true
                xml.mkp.xmlDeclaration(version: '1.0', encoding: "UTF-8")
                xml.packmetadata() {
                    sosdescription()
                    canAppliedMiddleware('Weblogic,Websphere 7.0,Yonyou Middleware V5,Yonyou Middleware V6')
                    canAppliedDB('DB2 V9.7,SQL Server 2008 R2,Oracle 10,Oracle 11')
                    patchType('BUG修复补丁')
                    modifiedJavaClasses(classtext)
                    modifiedModules("${realModuleName}")
                    needRecreatedLoginJar('false')
                    applyVersion('5.0,5.01,5.011,5.02,5.3,5.5,5.6,5.7,5.75,6.0,6.1,6.3')
                    patchName(gitPatchDescription.get())
                    bugs('')
                    provider(gitPatchAuthor.get())
                    patchPriority('高危补丁')
                    patchVersion('')
                    dependInfo('')
                    canAppliedOS('Linux,Windows,AIX,Solaris')
                    id(id1)
                    time(suffix)
                    department(gitPatchDepartment.get())
                    // tineedDeployme(false)
                    needDeploy(false)
                    searchKeys('')

                    // Leave file comment
                    mkp.yield('\n    ')
                    // mkp.comment("AUTO-GENERATED FILE.  DO NOT MODIFY. public.xml is generated by the generatepublicxml gradle task")
                }
            }

            def outputxml2 = outputxml.text.replace('sosdescription','description')
            outputxml.write(outputxml2, "UTF-8")


            // 写readme.txt
            def outputReadme = new File("${patchOutput}/readme.txt")
            def readme = """
            |        
            |==============================================================================
            |1)补丁基本信息
            |==============================================================================
            |
            |	补丁名称 - ${gitPatchDescription.get()}
            |	补丁编号 - ${id1}
            |	产品版本 - 
            |	补丁修改模块 - ${realModuleName}
            |	补丁依赖信息 - 
            |	适用的中间件平台 - Weblogic,Websphere 7.0,Yonyou Middleware V5,Yonyou Middleware V6
            |	适用的操作系统平台 - Linux,Windows,AIX,Solaris
            |	适用的数据库平台 - DB2 V9.7,SQL Server 2008 R2,Oracle 10,Oracle 11
            |	补丁创建时间 - ${suffix}
            |	是否需要部署 - false
            |	是否需要重新生成客户端Applet Jar包 - false
            |
            |==============================================================================
            |2)补丁安装步骤说明
            |==============================================================================
            |
            |	补丁安装前置准备工作(比如数据备份)
            |	======================================================================
            |
            |
            |	补丁安装
            |	======================================================================
            |	
            |
            |	补丁安装后置工作
            |	======================================================================
            |	1、重启服务
            |   2、清理浏览器缓存
            |
            |	补丁安装成功的验证工作
            |	======================================================================
            |
            |
            |	其它信息
            |	======================================================================
            |	
            |	
            |==============================================================================
            |3)补丁修复bug列表说明
            |==============================================================================
            |
            |
            |   补丁分支：
            |${branchName}
            |   提交描述：
            |${summary}     
            |
            |   文件列表：
            |${allFileLog.unique().sort().join('\n')}         
            |  
            |""".stripMargin()
            outputReadme.write(readme, "UTF-8")
        }

        doLast {

            println "  >>  ${prefixColor} 查看补丁（未压缩）: ${patchOutput}"
        }
    }


    // ##### method area #####

    def printlnUTF8(String text) {
        println new String(text.getBytes("UTF-8"), consoleEncoding.get())
    }

    /**
     * 读取XML标签的属性值
     *
     * @param tagName
     * @param attributeName
     * @return
     */
    def readModuleXmlNameAttribute(modulePath) {
        // 创建 XmlParser 实例
        XmlParser parser = new XmlParser()
        def moduleNode = parser.parse(new File("${modulePath}/META-INF/module.xml"))
        def name = moduleNode.@name
        return name
    }

    /**
     * 确保模块名存在
     *
     * @return
     */
    def ensureModuleName(modulePath) {
        def moduleName = readModuleXmlNameAttribute(modulePath)
        if (moduleName) {
            return moduleName
        }
        return gitPatchModuleName.get().replaceAll('\\w+_','').toLowerCase()
    }

    // end method area
}